module Damas where

import Char
import Tablero

data Juego = J Color Tablero
data Movimiento = M Posicion Direccion
  deriving Show

data Arbol a = Nodo a [Arbol a] deriving Show
type ArbolJugadas = Arbol ([Movimiento], Juego)

type Valuacion = Juego -> Double

---- Funciones de regalo ----

instance Show Juego where
  show (J turno tablero) = "\n--Juegan las " ++ show turno ++ "s--\n" ++ show tablero

arbolDeJugadas :: Juego -> ArbolJugadas
arbolDeJugadas j = Nodo ([], j) $ zipWith agmov movs hijos
  where agmov m (Nodo (ms, r) hs) = Nodo ((m:ms), r) (map (agmov m) hs)
        movsJuegos = movimientosPosibles j
        movs = map fst movsJuegos
        hijos = map (arbolDeJugadas . snd) movsJuegos

---- Ejercicios ----

-- Ejercicio 3

posicionFueraDelTablero :: Posicion -> Bool
posicionFueraDelTablero (i,j) = not (i `elem` ['a'..'h']) || not (j `elem` [1..8])

posicionMasDireccion :: Posicion -> Direccion -> Posicion
posicionMasDireccion (i,j) d | d == TL = (chr ((ord i) - 1), j+1)
                             | d == TR = (chr ((ord i) + 1), j+1)
                             | d == BL = (chr ((ord i) - 1), j-1)                                          
							 | d == BR = (chr ((ord i) + 1), j-1)

posicionMasDireccionTeniendoEnCuentaCaptura :: Posicion -> Direccion -> Tablero -> Posicion 
posicionMasDireccionTeniendoEnCuentaCaptura p d t = if contenido (posicionMasDireccion p d) t == Nothing then
														(posicionMasDireccion p d)
											  	    else
														 posicionMasDireccion (posicionMasDireccion p d) d

--Habria que ver si se puede hacer sin usar esta funcion
--no esta definida para Nothing
maybeFichaAFicha :: Maybe Ficha -> Ficha
maybeFichaAFicha (Just f) = f

color :: Ficha -> Color
color (Simple c) = c
color (Reina  c) = c

esCaptura :: Posicion -> Direccion -> Tablero -> Bool
esCaptura p d t = (posicionMasDireccion p d) /= (posicionMasDireccionTeniendoEnCuentaCaptura p d t)

esReina :: Ficha -> Bool
esReina (Simple c) = False
esReina (Reina c) = True

esSimple :: Ficha -> Bool
esSimple (Simple c) = True
esSimple (Reina c) = False

fichaSeMueveEnDireccionIncorrecta :: Ficha -> Direccion -> Bool
fichaSeMueveEnDireccionIncorrecta f d | esSimple f && (color f) == Negra  = if (d == TL || d == TR) then 
																			   True
																		    else
																		       False
									  | esSimple f && (color f) == Blanca = if (d == BL || d == BR) then
									                                           True
																			else
																			   False
									  | esReina  f = False
									  
invertirColor :: Color -> Color
invertirColor Blanca = Negra
invertirColor Negra  = Blanca

esPosicionCoronable :: Posicion -> Bool
esPosicionCoronable (i,j) = (j == 1 || j == 8)

coronar :: Ficha -> Ficha
coronar (Simple c) = (Reina c)
coronar (Reina c ) = (Reina c)

tableroDespuesDeMover :: Movimiento -> Tablero -> Tablero
tableroDespuesDeMover (M p d) t | (esCaptura p d t) = if esPosicionCoronable (posicionMasDireccionTeniendoEnCuentaCaptura p d t) then
														 (poner (coronar (maybeFichaAFicha (contenido p t))) (posicionMasDireccionTeniendoEnCuentaCaptura p d t) (sacar (posicionMasDireccion p d) (sacar p t)))
													  else
													     (poner (maybeFichaAFicha (contenido p t)) (posicionMasDireccionTeniendoEnCuentaCaptura p d t) (sacar (posicionMasDireccion p d) (sacar p t)))
								| otherwise = if esPosicionCoronable (posicionMasDireccionTeniendoEnCuentaCaptura p d t) then
												 (poner (coronar (maybeFichaAFicha (contenido p t))) (posicionMasDireccion p d) (sacar p t))
											  else
												 (poner (maybeFichaAFicha (contenido p t)) (posicionMasDireccion p d) (sacar p t))

{--
	El orden de las condiciones es el mismo que en el enunciado
	- Que las casillas de origen y destino no caigan fuera del tablero
	- Que haya una ficha en la casilla de origen
	- Que el color de la ficha movida coincida con el color del jugador al que le toca mover
	- Que la ficha se mueva en la direccion correcta, si no es una reina
	- Que la casilla de destino este libre
	- En caso de tratarse de una captura, que la casilla intermedia contenga una ficha del color del adversario
--}

mover :: Movimiento -> Juego -> Maybe Juego
mover (M p d) (J c t) | posicionFueraDelTablero p || posicionFueraDelTablero (posicionMasDireccionTeniendoEnCuentaCaptura p d t) = Nothing
					  | (contenido p t) == Nothing = Nothing
					  | color (maybeFichaAFicha (contenido p t)) /= c = Nothing
					  | fichaSeMueveEnDireccionIncorrecta (maybeFichaAFicha (contenido p t)) d = Nothing
					  | (contenido (posicionMasDireccionTeniendoEnCuentaCaptura p d t) t) /= Nothing = Nothing
					  | (esCaptura p d t) && (color (maybeFichaAFicha (contenido (posicionMasDireccion p d) t)) == c) = Nothing
					  | otherwise = Just (J (invertirColor c) (tableroDespuesDeMover (M p d) t))

-- Ejercicio 4
movimientosPosibles :: Juego -> [(Movimiento, Juego)]
movimientosPosibles = error "falta implementar"

-- Ejercicio 5
-- foldArbol :: ...

-- Ejercicio 6
-- podar :: Int -> Arbol a -> Arbol a

-- Ejercicio 7
-- minimax :: Valuacion -> ArbolJugadas -> (Double, [Movimiento])

-- Ejercicio 8
-- ganador :: Juego -> Maybe Color

-- Ejercicio 9
-- valuacionDamas :: Juego -> Double
